#pragma once

#include <typeinfo>

#include<cassert>


using namespace std;

//自定义的any类型
class Any
{
private:
    class Holder
    {
    public:
        // 保存的数据的具体类型
        virtual const type_info& Type() = 0;
        // 返回当前指向Placeholder对象的拷贝
        virtual Holder* Clone() = 0;
        virtual ~Holder()
        {
        }
    };
    template <class T>
    class Placeholder : public Holder
    {
    public:
        T _data;

    public:
        Placeholder(const T& data)
            : _data(data)
        {
        }
        // 保存的数据的具体类型
        virtual const type_info& Type()
        {
            return typeid(_data);
        }
        // 返回当前指向Placeholder对象的拷贝
        virtual Holder* Clone()
        {
            return new Placeholder(*this);
        }
    };

    //保存抽象父类Holder的指针，通过多态的特性实现Any
    Holder* _holder;

    void Swap(Any& obj)
    {
        std::swap(_holder,obj._holder);
    }
public:
    Any()
        :_holder(nullptr)
    {
    }
    template <class T>
    Any(const T& data)
        : _holder(new Placeholder<T>(data))
    {
    }
    Any(const Any& obj)
    {
        //防止空指针访问
        if (obj._holder != nullptr)
        {
            _holder = (obj._holder)->Clone();
        }
        else
        {
            _holder = nullptr;
        }
    }
    Any(Any&& obj)
    {
        //直接交换
        obj.Swap(*this);
    }

    template <class T>
    Any& operator=(const T&val)
    {
        Any(val).Swap(*this);
        return *this;
    }

    Any& operator=(Any obj)
    {
        obj.Swap(*this);
        return *this;
    }

    Any& operator=(Any&& obj)
    {
        obj.Swap(*this);
        return *this;
    }
    //获取Any中保存的数据
    template <class T>
    T& Data()
    {
        //必须类型一样才能获取
        assert(typeid(T) == _holder->Type());
        return ((Placeholder<T>*)_holder)->_data;
    }

    ~Any()
    {
        if (_holder != nullptr)
        {
            delete _holder;
            _holder = nullptr;
        }
    }
};
